using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.IO;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Collections.Generic;

namespace $ApplicationNamespace$.$ApplicationName$.STSADMExtension.$WSPSolutionName$
{
    internal class SPValidators
    {
        /// <summary>
        /// Validates the specified param A name.
        /// </summary>
        /// <param name="paramAName">Name of the param A.</param>
        /// <param name="paramAValue">The param A value.</param>
        /// <param name="paramBName">Name of the param B.</param>
        /// <param name="paramBValue">The param B value.</param>
        public static void Validate(string paramAName, string paramAValue, string paramBName, string paramBValue)
        {
            if ((paramAValue == null) && (paramBValue == null))
            {
                throw new ArgumentException(SPResource.GetString("MissingBinaryParameter", new object[] { paramAName, paramBName }));
            }
            if ((paramAValue != null) && (paramBValue != null))
            {
                throw new ArgumentException(SPResource.GetString("IncompatibleParametersSpecified", new object[] { paramAName, paramBName }));
            }
        }
    }

    public interface ISPValidator
    {
        bool Validate(string str);
        string ErrorInfo { get; }
    }

    internal class SPValidator : ISPValidator
    {

        public virtual bool Validate(string str)
        {
            return true;
        }
        private string m_errorInfo = null;
        public virtual string ErrorInfo
        {
            get { return m_errorInfo; }
            protected set { m_errorInfo = value; }
        }
    }

    internal class SPDirectoryExistsAndValidFileNameValidator : SPNonEmptyValidator
    {
        public override bool Validate(string str)
        {
            if (base.Validate(str))
            {
                try
                {
                    FileInfo info = new FileInfo(str);
                    if (info.Directory.Exists)
                    {
                        if (info.Name.EndsWith("\\") || info.Name.EndsWith("/"))
                        {
                            ErrorInfo = "Filename not specified";
                            throw new SPException(SPResource.GetString("StsadmReqFileName", new object[0]));
                        }

                        return true;
                    }
                    else
                    {
                        ErrorInfo = "Directory not found";
                        throw new DirectoryNotFoundException();
                    }
                }
                catch
                {
                    return false;
                }
            }
            return false;
        }
    }

    internal class SPDirectoryExistsValidator : SPNonEmptyValidator
    {
        public override bool Validate(string str)
        {
            if (base.Validate(str))
            {
                try
                {
                    if (Directory.Exists(str))
                    {
                        return true;
                    }
                    else
                    {
                        ErrorInfo = "Directory not found";
                        throw new DirectoryNotFoundException();
                    }
                }
                catch
                {
                    return false;
                }
            }
            return false;
        }
    }

    internal class SPEnableDisableValidator : SPValidator
    {
        /// <summary>
        /// Validates the specified string.
        /// </summary>
        /// <param name="str">The string to validate.</param>
        /// <returns></returns>
        public override bool Validate(string str)
        {
            if ((str != null) && (str.Trim().Length != 0))
            {
                if ((str.CompareTo("enable") != 0) && (str.CompareTo("disable") != 0))
                {
                    return false;
                }
                return true;
            }
            return false;
        }
    }

    internal class SPEnumValidator : SPRegexValidator
    {
        private Type enumTypeValue;
        private string[] additionalValues = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="SPEnumValidator"/> class.
        /// </summary>
        /// <param name="enumType">Type of the enum.</param>
        public SPEnumValidator(Type enumType)
            : base(GetEnumRegex(enumType, null), SPRegexValidationType.Legal)
        {
            enumTypeValue = enumType;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SPEnumValidator"/> class.
        /// </summary>
        /// <param name="enumType">Type of the enum.</param>
        /// <param name="additionalValues">The additional values.</param>
        public SPEnumValidator(Type enumType, string[] additionalValues)
            : base(GetEnumRegex(enumType, additionalValues), SPRegexValidationType.Legal)
        {
            enumTypeValue = enumType;
            this.additionalValues = additionalValues;
        }

        /// <summary>
        /// Gets the enum regex.
        /// </summary>
        /// <param name="enumType">Type of the enum.</param>
        /// <param name="additionalValues">The additional values.</param>
        /// <returns></returns>
        private static string GetEnumRegex(Type enumType, string[] additionalValues)
        {
            if (!enumType.IsEnum)
                throw new Exception("Type is not an enum type.");

            string regex = string.Join("$|^", Enum.GetNames(enumType));
            if (additionalValues != null && additionalValues.Length > 0)
                regex += "$|^" + string.Join("$|^", additionalValues);

            regex = "(?i:^" + regex + "$)";
            return regex;
        }

        /// <summary>
        /// Gets the display value.
        /// </summary>
        /// <value>The display value.</value>
        internal string DisplayValue
        {
            get
            {
                string val = string.Join(" | ", Enum.GetNames(enumTypeValue));
                if (additionalValues != null && additionalValues.Length > 0)
                    val += " | " + string.Join(" | ", additionalValues);
                return val.ToLowerInvariant();
            }
        }
    }

    internal class SPFileExistsValidator : SPNonEmptyValidator
    {
        /// <summary>
        /// Validates that the specified file exists.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <returns></returns>
        public override bool Validate(string filename)
        {
            if (!base.Validate(filename))
            {
                return false;
            }
            return File.Exists(filename);
        }
    }

    internal class SPGuidValidator : SPNonEmptyValidator
    {
        /// <summary>
        /// Validates the specified GUID.
        /// </summary>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public override bool Validate(string guid)
        {
            if (base.Validate(guid))
            {
                try
                {
                    new Guid(guid);
                    return true;
                }
                catch (UriFormatException)
                {
                    return false;
                }
            }
            return false;
        }
    }

    internal class SPZoneUrlValidator : SPValidator
    {
        /// <summary>
        /// Validates the specified string.
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns></returns>
        public override bool Validate(string str)
        {
            if (str != null)
            {
                while (str.Trim().Length != 0)
                {
                    try
                    {
                        SPUrlZoneParser.Parse(str);
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                }
            }
            return false;
        }
    }

    internal class SPIntRangeValidator : SPNonEmptyValidator
    {
        private int m_nLower;
        private int m_nUpper;

        public SPIntRangeValidator(int nLower, int nUpper)
        {
            m_nLower = nLower;
            m_nUpper = nUpper;
        }

        public override bool Validate(string strParam)
        {
            if (!base.Validate(strParam))
            {
                return false;
            }
            int num = int.Parse(strParam);
            if (m_nLower > num)
            {
                return false;
            }
            return (num <= m_nUpper);
        }
    }

    internal class SPLongRangeValidator : SPNonEmptyValidator
    {
        private long m_nLower;
        private long m_nUpper;

        public SPLongRangeValidator(long nLower, long nUpper)
        {
            m_nLower = nLower;
            m_nUpper = nUpper;
        }

        public override bool Validate(string strParam)
        {
            if (!base.Validate(strParam))
            {
                return false;
            }
            long num = long.Parse(strParam);
            if (m_nLower > num)
            {
                return false;
            }
            return (num <= m_nUpper);
        }
    }

    internal class SPMultiParameterValidator
    {
        /// <summary>
        /// Validates the specified param A name.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="possibleParams">The possible params.</param>
        /// <param name="minAllowed">The min allowed.</param>
        /// <param name="maxAllowed">The max allowed.</param>
        public static void Validate(SPParamCollection parameters, string[] possibleParams, int minAllowed, int maxAllowed)
        {
            List<SPParam> foundParams = new List<SPParam>();
            foreach (string param in possibleParams)
            {
                if (parameters[param.ToLowerInvariant()].UserTypedIn)
                    foundParams.Add(parameters[param.ToLowerInvariant()]);
            }
            if (foundParams.Count < minAllowed || foundParams.Count > maxAllowed)
            {
                if (minAllowed == maxAllowed)
                    throw new ArgumentException(
                        string.Format("You must specify only {0} of the following parameters: {1}", minAllowed,
                                      string.Join(", ", possibleParams)));
                else if (minAllowed != maxAllowed)
                {
                    throw new ArgumentException(
                        string.Format(
                            "You must specify at least {0} and no more than {1} of the following parameters: {2}",
                            minAllowed, maxAllowed, string.Join(", ", possibleParams)));
                }
            }
        }
    }

    internal class SPNonEmptyValidator : SPValidator
    {
        /// <summary>
        /// Validates the specified string.
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns></returns>
        public override bool Validate(string str)
        {
            return ((str != null) && (str.Trim().Length != 0));
        }
    }

    internal class SPNullOrNonEmptyValidator : SPValidator
    {
        /// <summary>
        /// Validates the specified string.
        /// </summary>
        /// <param name="str">The string.</param>
        /// <returns></returns>
        public override bool Validate(string str)
        {
            if ((str != null) && (str.Trim().Length <= 0))
            {
                return false;
            }
            return true;
        }
    }

    internal class SPRegexValidator : SPNonEmptyValidator
    {
        private string m_strRegex;
        private SPRegexValidationType m_validationType;

        /// <summary>
        /// Initializes a new instance of the <see cref="SPRegexValidator"/> class.
        /// </summary>
        /// <param name="strRegex">The regex.</param>
        public SPRegexValidator(string strRegex)
            : this(strRegex, SPRegexValidationType.Legal)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SPRegexValidator"/> class.
        /// </summary>
        /// <param name="strRegex">The regex.</param>
        /// <param name="validationType">Type of the validation.</param>
        public SPRegexValidator(string strRegex, SPRegexValidationType validationType)
        {
            m_strRegex = strRegex;
            m_validationType = validationType;
        }

        /// <summary>
        /// Validates the specified parameter value.
        /// </summary>
        /// <param name="parameterValue">The parameter value.</param>
        /// <returns></returns>
        public override bool Validate(string parameterValue)
        {
            if (!base.Validate(parameterValue))
            {
                return false;
            }
            Regex regex = new Regex(m_strRegex);
            parameterValue = parameterValue.ToLower(CultureInfo.InvariantCulture);
            bool success = regex.Match(parameterValue).Success;
            if (m_validationType != SPRegexValidationType.Legal)
            {
                if (success)
                {
                    return false;
                }
                return base.Validate(parameterValue);
            }
            if (!success)
            {
                return false;
            }
            return base.Validate(parameterValue);
        }
    }

    internal enum SPRegexValidationType
    {
        Legal,
        Illegal
    }

    internal class SPTriParameterValidator
    {
        /// <summary>
        /// Validates the specified param A name.
        /// </summary>
        /// <param name="paramAName">Name of the param A.</param>
        /// <param name="paramAValue">The param A value.</param>
        /// <param name="paramBName">Name of the param B.</param>
        /// <param name="paramBValue">The param B value.</param>
        /// <param name="paramCName">Name of the param C.</param>
        /// <param name="paramCValue">The param C value.</param>
        public static void Validate(string paramAName, string paramAValue, string paramBName, string paramBValue, string paramCName, string paramCValue)
        {
            if ((paramAValue == null) && (paramBValue == null) && (paramCValue == null))
            {
                throw new ArgumentException(string.Format("Specify either the {0}, the {1}, or the {2} parameters with this command.", paramAName, paramBName, paramCName));
            }
            if ((paramAValue != null) && (paramBValue != null) && paramCValue != null)
                throw new ArgumentException(string.Format("The {0}, {1}, and {2} parameters are not compatible.  Please specify one or the other.", paramAName, paramBName, paramCName));
            if ((paramAValue != null) && (paramBValue != null))
            {
                throw new ArgumentException(SPResource.GetString("IncompatibleParametersSpecified", new object[] { paramAName, paramBName }));
            }
            if ((paramAValue != null) && (paramCValue != null))
            {
                throw new ArgumentException(SPResource.GetString("IncompatibleParametersSpecified", new object[] { paramAName, paramCName }));
            }
            if ((paramBValue != null) && (paramCValue != null))
            {
                throw new ArgumentException(SPResource.GetString("IncompatibleParametersSpecified", new object[] { paramBName, paramCName }));
            }
        }
    }

    internal class SPTrueFalseValidator : SPValidator
    {
        /// <summary>
        /// Validates the specified string.
        /// </summary>
        /// <param name="str">The string to validate.</param>
        /// <returns></returns>
        public override bool Validate(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                if ((str.CompareTo("true") != 0) && (str.CompareTo("false") != 0))
                {
                    return false;
                }
                return true;
            }
            return false;
        }
    }

    internal class SPUrlValidator : SPNonEmptyValidator
    {
        // Methods
        public override bool Validate(string str)
        {
            if (base.Validate(str))
            {
                bool flag;
                if (str.IndexOf('\\') >= 0)
                {
                    return false;
                }
                try
                {
                    Uri uri = new Uri(str);
                    if (uri.Fragment == "")
                    {
                        if (uri.Query == "")
                        {
                            if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)
                            {
                                return true;
                            }
                            return false;
                        }
                    }
                    flag = false;
                }
                catch (UriFormatException)
                {
                    flag = false;
                }
                return flag;
            }
            return false;
        }
    }

    internal class SPUrlZoneParser
    {
        /// <summary>
        /// Parses the specified URL zone.
        /// </summary>
        /// <param name="strUrlZone">The URL zone.</param>
        /// <returns></returns>
        public static SPUrlZone Parse(string strUrlZone)
        {
            strUrlZone = strUrlZone.Trim().ToLower(CultureInfo.InvariantCulture);
            string str = strUrlZone;
            if (str != null)
            {
                if (str == "default")
                {
                    return SPUrlZone.Default;
                }
                if (str == "intranet")
                {
                    return SPUrlZone.Intranet;
                }
                switch (str)
                {
                    case "internet":
                        return SPUrlZone.Internet;

                    case "extranet":
                        return SPUrlZone.Extranet;

                    default:
                        if (str == "custom")
                        {
                            return SPUrlZone.Custom;
                        }
                        break;
                }
            }
            throw new ArgumentException(SPResource.GetString("ZoneNotFound", new object[] { strUrlZone }));
        }
    }
}
